package com.ls.hiprintSpire.utils;

import com.alibaba.fastjson.JSON;
import com.spire.barcode.*;
import com.spire.ms.System.Collections.IEnumerator;
import com.spire.pdf.*;
import com.spire.pdf.automaticfields.PdfAutomaticField;
import com.spire.pdf.automaticfields.PdfCompositeField;
import com.spire.pdf.automaticfields.PdfPageCountField;
import com.spire.pdf.automaticfields.PdfPageNumberField;
import com.spire.pdf.barcode.PdfCodabarBarcode;
import com.spire.pdf.barcode.PdfCode39Barcode;
import com.spire.pdf.barcode.TextLocation;
import com.spire.pdf.fields.PdfTextBoxField;
import com.spire.pdf.graphics.*;
import com.spire.pdf.grid.PdfGrid;
import com.spire.pdf.grid.PdfGridCell;
import com.spire.pdf.grid.PdfGridHeaderCollection;
import com.spire.pdf.grid.PdfGridRow;
import com.spire.pdf.tables.PdfBorderOverlapStyle;
import com.sun.xml.internal.ws.util.StringUtils;
import entry.Column;
import entry.Panel;
import entry.Panels;
import entry.PrintElements;
import entry.options.*;
import enums.OptionsTextTypeEnums;
import enums.PrintElementTypeEnums;
import lombok.Data;
import org.apache.commons.collections4.ListUtils;

import java.awt.*;
import java.awt.geom.Dimension2D;
import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;
import java.awt.image.BufferedImage;
import java.lang.reflect.Field;
import java.util.*;
import java.util.List;
import java.util.regex.Pattern;

/**
 * @Author LS
 * @Date 2023/4/17 9:23
 * @Description
 **/

public class HiPrintSpireUtils {

    private PdfDocument pdfDocument;

    // 毫米转换像素参数
    private final double mmToPx = 2.83;

    // PDF结构
    private Panels panels;

    // 根据页面下标置入
    private List<PdfPageBase> pageCache;

    // 未完成数据填充的页面
    private List<PdfPageBase> notIssuePageCache = new ArrayList<>();

    // 工具类所需数据
    private UtilData utilData;

    // page对应的所需绘制表格
    private Map<PdfPageBase, Map<TableOptions, Rectangle2D>> pageTableCache = new HashMap<>();

    // 需要进行打印的数据
    private Map<PdfPageBase, List<PrintElements>> printElementsPageCache = new HashMap<>();

    // 构建工具类时未传入，新建pdf
    // 传入pdf结构json
    public HiPrintSpireUtils(String json){
        this(new PdfDocument(), json, null);
    }

    public HiPrintSpireUtils(PdfDocument document, String json){
        this(document, json, null);
    }

    public HiPrintSpireUtils(PdfDocument document, String json, UtilData utilData){
        pdfDocument = document;
        panels = getPanels(json);
        setUtilData(utilData);
        pageCache = new ArrayList<>(panels.getPanels().size());
    }


    /**
     * 根据pdf结构Json生成对应的java实体
     * @param json
     * @return
     */
    private Panels getPanels(String json){
        return JSON.parseObject(json, Panels.class);
    }

    public void setUtilData(UtilData utilData){
        this.utilData = utilData;
    }

    @Data
    public static class UtilData {
        // 文本框绑定的字段 Map<'fieldKey', 'filedValue'>
        private Map<String, String> fields = new HashMap<>();

        // 每个表格对应的数据 Map<'tableKey', List<Map<'headerKey','fieldValue'>>> 若无headerKey兼容headerName
        private Map<String, List<Map<String, String>>> tableData = new HashMap<>();
    }



    /**
     *  根据Panel参数创建页面
     * @param panel
     * @return
     */
    private PdfPageBase createPage(Panel panel, boolean addCache){
        Dimension2D dimension2D = new Dimension((int) (panel.getWidth() * mmToPx), (int) (panel.getHeight() * mmToPx));
        PdfPageBase pageBase = pdfDocument.getPages().add(dimension2D, new PdfMargins(0));
        if (addCache){
            pageCache.add(panel.getIndex(), pageBase);
        }
        else {
            notIssuePageCache.add(pageBase);
        }
        return pageBase;
    }

    private PdfPageBase createPage(Panel panel) {
        return this.createPage(panel, true);
    }

        /**
         * 通过PDF结构进行创建
         * @throws Exception
         */
    public void save(String filePath) throws Exception {
        for (Panel panel : panels.getPanels()) {
            // 创建页面
            PdfPageBase page = createPage(panel);
            List<PrintElements> printElements = panel.getPrintElements();
            for (PrintElements printElement : printElements) {
                dealOptions(page, printElement);
            }
            // 创建页尾
            createFooter(page, panel);
        }
        // 遍历对应的page与textOption
        for (Map.Entry<PdfPageBase, Map<TableOptions, Rectangle2D>> next : pageTableCache.entrySet()) {
            PdfPageBase pageBase = next.getKey();
            Map<TableOptions, Rectangle2D> value = next.getValue();
            for (Map.Entry<TableOptions, Rectangle2D> tableOptionsMap : value.entrySet()) {
                TableOptions tableOptions = tableOptionsMap.getKey();
                Rectangle2D position = tableOptionsMap.getValue();
                // 创建表格
                createTable(pageBase, tableOptions, position);
            }
        }
        Collection<List<PrintElements>> values = printElementsPageCache.values();
        if (!values.isEmpty()) {
            List<PrintElements> printElementsList = new ArrayList<>();
            values.forEach(printElementsList::addAll);
            // 循环未进行其他打印元素缓存
            for (PdfPageBase pageBase : notIssuePageCache) {
                for (PrintElements printElements : printElementsList) {
                    dealOptions(pageBase, printElements);
                }
            }
        }

        pdfDocument.saveToFile(filePath);
        pdfDocument.close();
    }

    /**
     * 处理Options结构，根据不同的Options生成不同的PDF元素
     * @param pageBase
     * @param printElement
     */
    private void dealOptions(PdfPageBase pageBase, PrintElements printElement) throws Exception {
        Options options = printElement.getOptions();
        double left = options.getLeft();
        double top = options.getTop();
        double height = options.getHeight();
        double width = options.getWidth();
        // 获取Position打印位置
        Rectangle2D.Double position = new Rectangle2D.Double(left, top, width, height);
        if (options instanceof TextOptions){
            TextOptions textOptions = (TextOptions) options;
            OptionsTextTypeEnums textType = textOptions.getTextType();
            // 若传入字段不为空，需要通过数据字段获取值
            if (OptionsTextTypeEnums.TEXT.equals(textType)){
                // 无字段名时，绘制text
                if (textOptions.getField() != null){
                    createTextBoxField(pageBase, textOptions, position);
                }else {
                    // 绘制字符串
                    createString(pageBase, textOptions, position);
                }
            }else if (OptionsTextTypeEnums.BARCODE.equals(textType)){
                double barcodeHeight = height + textOptions.getFontSize() + 1;
                Rectangle2D.Double barcodePosition = new Rectangle2D.Double(left, top, width, barcodeHeight);
                createBarcode(pageBase, textOptions, barcodePosition);
            }else if (OptionsTextTypeEnums.QRCODE.equals(textType)){
                createQrcode(pageBase, textOptions, position);
            }else {
                // 不是有效枚举，跳过插入元素 todo doLog
            }
        }else if (options instanceof LongTextOptions){
            LongTextOptions longTextOptions = (LongTextOptions) options;
            createLongText(pageBase, longTextOptions, position);
        }else if (options instanceof TableOptions){
            // todo 根据绘制方式区分绘制方式，
            //  1、表格数据大于表格大小时，复制当前页面所有数据，另起一页
            //  2、表格数据往后推并且是否重复表头
            TableOptions tableOptions = (TableOptions) options;
//            createTable(pageBase, tableOptions, position);
            // 后置绘制，根据不同的方式绘制页面
            addPageTableCache(pageBase, tableOptions, position);
        }else if (options instanceof ImageOptions){
            ImageOptions imageOptions = (ImageOptions) options;
            createImage(pageBase, imageOptions, position);
        }else if (options instanceof  GraphicalOptions){
            createGraph(pageBase, printElement, position);
        }else {
            throw new RuntimeException("无效元素");
        }
        // 不为表格类型的打印数据进行缓存
        if (! (options instanceof TableOptions)){
            // 加入打印缓存
            addPrintElementsPageCache(pageBase, printElement);
        }
    }

    /**
     * 加入缓存，后续进行绘制，绘制内容范围为table范围
     * @param pageBase
     * @param tableOptions
     * @param position
     */
    private void addPageTableCache(PdfPageBase pageBase, TableOptions tableOptions, Rectangle2D position){
        // 检查缓存
        if (pageTableCache == null) {
            pageTableCache = new HashMap<>();
        }
        // 若不存在pageKey，直接存入
        if (!pageTableCache.containsKey(pageBase)){
            Map<TableOptions, Rectangle2D> map = new HashMap<>();
            map.put(tableOptions, position);
            pageTableCache.putIfAbsent(pageBase, map);
        }
        else {
            Map<TableOptions, Rectangle2D> map = pageTableCache.get(pageBase);
            map.putIfAbsent(tableOptions, position);
            pageTableCache.put(pageBase, map);
        }
    }

    /**
     * 增加页面对应的打印数据缓存
     * @param pageBase
     * @param printElements
     */
    private void addPrintElementsPageCache(PdfPageBase pageBase, PrintElements printElements){
        if (printElementsPageCache == null) {
            printElementsPageCache = new HashMap<>();
        }
        if (printElementsPageCache.containsKey(pageBase)) {
            List<PrintElements> printElementsList = printElementsPageCache.get(pageBase);
            printElementsList.add(printElements);
            printElementsPageCache.put(pageBase, printElementsList);
        }
        else {
            ArrayList<PrintElements> printElementsList = new ArrayList<>();
            printElementsList.add(printElements);
            printElementsPageCache.put(pageBase, printElementsList);
        }
    }

    /**
     * 创建页尾
     * @param pageBase
     * @param panel
     * @throws IllegalAccessException
     */
    private void createFooter(PdfPageBase pageBase, Panel panel) throws IllegalAccessException {
        PdfMargins margin = new PdfMargins(30,30,20,40);
//        PdfPageTemplateElement footer = new PdfPageTemplateElement(rectangle2D.getWidth(), getFont().getHeight());
        PdfPageTemplateElement footer = new PdfPageTemplateElement(panel.getPaperNumberLeft(), margin.getBottom());
        footer.setForeground(true);
        pdfDocument.getTemplate().setBottom(footer);

//        footer.getGraphics().setTransparency(0.5f);
////        footer.getGraphics().drawLine(new PdfPen(new PdfRGBColor(Color.black), 0.75f),
////                rectangle2D.getWidth()-10, rectangle2D.getHeight()-10, rectangle2D.getWidth() - 9, rectangle2D.getHeight() - 9);
//        float y = getFont().getHeight();
//        footer.getGraphics().drawLine(new PdfPen(new PdfRGBColor(Color.black), 0.75f),
//                margin.getLeft(), y, rectangle2D.getWidth() - margin.getRight(), y);
        PdfPageNumberField pageNumber = new PdfPageNumberField();
        PdfPageCountField pageCount = new PdfPageCountField();
        PdfCompositeField pageNumberLabel = new PdfCompositeField();
        pageNumberLabel.setAutomaticFields(new PdfAutomaticField[]{pageNumber, pageCount});
        pageNumberLabel.setBrush(PdfBrushes.getBlack());
        pageNumberLabel.setFont(getFont());
        PdfStringFormat format = new PdfStringFormat(PdfTextAlignment.Right);
        pageNumberLabel.setStringFormat(format);
        pageNumberLabel.setText("{0}-{1}");
        pageNumberLabel.setBounds(footer.getBounds());
        float y = getFont().getHeight();
        pageNumberLabel.draw(footer.getGraphics(), - margin.getLeft(), y);
    }

    /**
     * 创建图形
     * @param pageBase
     * @param printElement
     * @param position
     */
    private void createGraph(PdfPageBase pageBase, PrintElements printElement, Rectangle2D position) {
        PrintElementTypeEnums type = printElement.getPrintElementType().getType();
        PdfPen pen =new PdfPen(new PdfRGBColor(Color.black), Font.PLAIN);

        if (PrintElementTypeEnums.HLINE.equals(type)){
            // 横线
            Point2D start = new Point2D.Double(position.getX(), position.getY());
            Point2D end = new Point2D.Double(position.getX() + position.getWidth(), position.getY());
            pageBase.getCanvas().drawLine(pen, start, end);
        }else if (PrintElementTypeEnums.VLINE.equals(type)){
            // 竖线
            Point2D start = new Point2D.Double(position.getX(), position.getY());
            Point2D end = new Point2D.Double(position.getX(), position.getY() + position.getHeight());
            pageBase.getCanvas().drawLine(pen, start, end);
        }else if (PrintElementTypeEnums.HTML.equals(type)){
            // todo 暂未实现
        }else if (PrintElementTypeEnums.RECT.equals(type)){
            // 矩形
            pageBase.getCanvas().drawRectangle(pen, position);
        }else if (PrintElementTypeEnums.OVAL.equals(type)){
            // 椭圆
            pageBase.getCanvas().drawEllipse(pen, position);
        }else {
            throw new RuntimeException("无效元素");
        }
    }

    /**
     * 创建图片
     * @param pageBase
     * @param imageOptions
     * @param position
     */
    private void createImage(PdfPageBase pageBase, ImageOptions imageOptions, Rectangle2D position) {
        String field = imageOptions.getField();
        String value = imageOptions.getSrc();
        if (field != null && !field.isEmpty()){
            if (utilData != null && utilData.getFields() != null){
                String data = utilData.getFields().get(field);
                if (data != null){
                    value = data;
                }
            }
        }
        if (value != null){
            //加载图像
            PdfImage image = PdfImage.fromFile(value);
            // 绘制图片
            pageBase.getCanvas().drawImage(image, position);
        }
    }

    /**
     * 创建表格
     * @param pageBase
     * @param tableOptions
     * @param position
     */
    private void createTable(PdfPageBase pageBase, TableOptions tableOptions, Rectangle2D position) throws IllegalAccessException {
//        if (utilData.getTableHeaders() == null){
//            return;
//        }
        List<Column> columns = tableOptions.getColumns().get(0);
        //创建一个PdfGrid对象
        PdfGrid grid = new PdfGrid();
        // 表体字体
        PdfTrueTypeFont font = getFont(tableOptions.getFontSize(), tableOptions.getFontFamily(), Font.PLAIN);
        // 表头字体
        PdfTrueTypeFont headerFont = getFont(tableOptions.getTableHeaderFontSize(), tableOptions.getFontFamily(), tableOptions.getTableHeaderFontWeight());
        // 表头背景色
        PdfSolidBrush headerBrush = new PdfSolidBrush(new PdfRGBColor(hex2RGB(tableOptions.getTableHeaderBackground(), new Color(232, 232, 232))));

        // 表格样式
        grid.getStyle().setFont(font);
        grid.getStyle().setTextBrush(PdfBrushes.getBlack());
        grid.getColumns().add(columns.size());
//        grid.getStyle().setCellPadding(new PdfPaddings(5,5,3,3));

        // 创建表头行
        PdfGridRow[] headerRows = grid.getHeaders().add(1);
        for (int headerRowIndex = 0; headerRowIndex < headerRows.length; headerRowIndex++) {
            PdfGridRow headerRow = headerRows[headerRowIndex];
            // 循环表头
            for (int columnIndex = 0; columnIndex < columns.size(); columnIndex++) {
                Column column = columns.get(columnIndex);
                PdfGridCell headerCell = headerRow.getCells().get(columnIndex);

                // 表头名称
                String columnTitle = column.getTitle();
                headerCell.setValue(columnTitle);

                headerCell.setRowSpan(column.getRowspan());
                headerCell.setColumnSpan(column.getColspan());

                // 设置单元格样式
                headerCell.getStyle().setTextBrush(PdfBrushes.getBlack());
                headerCell.getStyle().setFont(headerFont);
                headerCell.getStyle().setBackgroundBrush(headerBrush);
                // todo 表头边框
                headerCell.getStyle().setBorders(PdfBorders.getDefault());
                // todo 行间距
//            headerCell.getStyle().getStringFormat().setLineSpacing();
                // todo 最低高度，行高度
//
                // todo 单元格垂直与水平样式
                headerCell.getStyle().getStringFormat().setLineAlignment(PdfVerticalAlignment.Middle);
                headerCell.getStyle().getStringFormat().setAlignment(PdfTextAlignment.valueOf(StringUtils.capitalize(tableOptions.getTextAlign().name().toLowerCase())));
            }
        }
        // todo 填充数据，此处暂时使用方案1   1、表格数据大于表格大小时，复制当前页面所有数据，另起一页
        fillData(pageBase, tableOptions, position, grid);
        // todo 填充数据的时候进行分页
        grid.draw(pageBase, position);
    }

    /**
     * 填充表格数据
     * @param pageBase
     * @param tableOptions
     * @param position
     * @param grid
     */
    private void fillData(PdfPageBase pageBase, TableOptions tableOptions, Rectangle2D position, PdfGrid grid) throws IllegalAccessException {
        // 表格绑定字段
        String tableField = tableOptions.getField();
        List<Column> columns = tableOptions.getColumns().get(0);
        // 填充数据
        if (utilData != null && !utilData.getTableData().isEmpty()){
            int tableMaxSize = getTableMaxSize(tableOptions, position, grid);
            Map<String, List<Map<String, String>>> tableData = utilData.getTableData();
            // 获取传入数据
            List<Map<String, String>> utilDataList = utilData.getTableData().get(tableField);
            // 分割数据大小
            List<List<Map<String, String>>> partition = ListUtils.partition(utilDataList, tableMaxSize);
            List<Map<String, String>> columnData = new ArrayList<>(partition.get(0));
            // 循环分割后的数据
            for (Map<String, String> columnDatum : columnData) {
                // 新增一行
                PdfGridRow row = grid.getRows().add();
                // 设置行高
                if (tableOptions.getTableBodyRowHeight() > 0){
                    row.setHeight((float) tableOptions.getTableBodyRowHeight());
                }
                for (int columnIndex = 0; columnIndex < columns.size(); columnIndex++) {
                    Column column = columns.get(columnIndex);
                    // 数据单元格
                    PdfGridCell dataCell = row.getCells().get(columnIndex);

                    // 通过表头ID获取值
                    String columnValueByField = columnDatum.get(column.getField());
                    // 通过表头名称获取值
                    String columnValueByTitle = columnDatum.get(column.getTitle());
                    String columnValue = null;
                    if (columnValueByField != null){
                        columnValue = columnValueByField;
                    }
                    if (columnValueByTitle != null){
                        columnValue = columnValueByTitle;
                    }
                    // 设置值
                    dataCell.setValue(columnValue);
                }
            }
            utilDataList.removeAll(columnData);
            // 移除数据
            tableData.put(tableField, utilDataList);
            // 更新缓存
            utilData.setTableData(tableData);
            // 仍存在数据，新建一页并填充表单
            if (!tableData.get(tableField).isEmpty()) {
                for (Panel panel : panels.getPanels()) {
                    PdfPageBase newPage = createPage(panel, false);
                    createTable(newPage, tableOptions, position);
                }
            }
        }
    }

    /**
     * 获取当前表格数据最大数量
     * @param tableOptions
     * @param position
     * @param grid
     * @return
     */
    private int getTableMaxSize(TableOptions tableOptions, Rectangle2D position, PdfGrid grid) throws IllegalAccessException {
        double height = position.getHeight();
        double tableBodyRowHeight = tableOptions.getTableBodyRowHeight();
        if (tableBodyRowHeight <= 0){
            tableBodyRowHeight = getFont(tableOptions.getFontSize(), tableOptions.getFontFamily(), Font.PLAIN).getHeight();
        }
        double tableHeaderRowHeight = tableOptions.getTableHeaderRowHeight();
        IEnumerator iterator = grid.getHeaders().iterator();
        PdfGridRow row = grid.getHeaders().get(0);
        double headerHeight = 0d;
        // 获取表头行数
        while (iterator.hasNext()) {
            PdfGridRow pdfGridRow = (PdfGridRow) iterator.next();
            headerHeight += pdfGridRow.getHeight();
        }
        return (int) ((height - headerHeight) / tableBodyRowHeight);
    }

    /**
     * 创建长文本框
     * @param pageBase
     * @param longTextOptions
     * @param position
     * @throws Exception
     */
    private void createLongText(PdfPageBase pageBase, LongTextOptions longTextOptions, Rectangle2D position) throws Exception {
        String field = longTextOptions.getField();
        // 创建文本输入框
        PdfTextBoxField textBoxField = new PdfTextBoxField(pageBase, field);
        textBoxField.setMultiline(true);
        // 设置打印位置
        textBoxField.setBounds(position);
        // 设置背景颜色
        textBoxField.setBackColor(new PdfRGBColor(hex2RGB(longTextOptions.getBackgroundColor(), Color.WHITE)));
        // 边框颜色
        textBoxField.setBorderColor(new PdfRGBColor(hex2RGB(longTextOptions.getBorderColor(), Color.BLACK)));
        textBoxField.setBorderWidth(getBorderWidth(longTextOptions.getBorderWidth(), 0f));
        // todo 边框样式
//        textBoxField.setBorderStyle();
        // todo 内边距
//
        // 文本框字体样式
        textBoxField.setFont(getFont(longTextOptions.getFontSize(), longTextOptions.getFontFamily(), longTextOptions.getFontWeight()));

        // todo 字体颜色
//
        // 设置值
        String title = longTextOptions.getTitle();
        String textValue = "";
        if (title != null && !title.isEmpty()){
            boolean hideTitle = longTextOptions.isHideTitle();
            String utilDataValue = null;
            // 获取字段中的值
            if (utilData != null && utilData.getFields() != null) {
                utilDataValue = utilData.getFields().get(longTextOptions.getField());
            }
            // 是否隐藏标题
            if (hideTitle){
                title = null;
            }
            // 若不隐藏标题，拼接title与utilDataValue
            if (title != null){
                StringBuilder stringBuilder = new StringBuilder(title);
                stringBuilder.append(":");
                if (utilDataValue != null){
                    stringBuilder.append(utilDataValue);
                }
                textValue = stringBuilder.toString();
            }else {
                // 标题为空，传入数据不为空，进行赋值
                if (utilDataValue != null){
                    textValue = utilDataValue;
                }
            }
        }
        textBoxField.setText(textValue);
        // 水平居中
        textBoxField.setTextAlignment(PdfTextAlignment.valueOf(StringUtils.capitalize(longTextOptions.getTextAlign().name().toLowerCase())));
        // todo 垂直居中
//
        pdfDocument.getForm().getFields().add(textBoxField);
        // todo addCache
    }

    /**
     * 创建二维码
     * @param pageBase
     * @param textOptions
     * @param position
     */
    private void createQrcode(PdfPageBase pageBase, TextOptions textOptions, Rectangle2D position){
        String field = textOptions.getField();
        String value = null;
        if (field != null && !field.isEmpty()){
            if (utilData != null && utilData.getFields() != null){
                value = utilData.getFields().get(field);
            }
        }
        if (value == null){
            value = textOptions.getTitle();
        }

        BarcodeSettings settings = new BarcodeSettings();
        settings.setType(BarCodeType.QR_Code);
        settings.setData(value);
//        settings.setData2D(value);
//        settings.setX(textOptions.getLineHeight());
//        settings.setLeftMargin();
        settings.setShowTextOnBottom(false);
        settings.setQRCodeECL(QRCodeECL.Q);
        settings.setQRCodeDataMode(QRCodeDataMode.Numeric);

        //生成二维码图片
        BarCodeGenerator generator = new BarCodeGenerator(settings);

        Image image = generator.generateImage();

        PdfImage pdfImage = PdfImage.fromImage((BufferedImage)image);
        pageBase.getCanvas().drawImage(pdfImage, position);
    }

    /**
     * 创建条形码
     * @param pageBase
     * @param textOptions
     * @param position
     */
    private void createBarcode(PdfPageBase pageBase, TextOptions textOptions, Rectangle2D position) throws IllegalAccessException {
        String field = textOptions.getField();
        // todo 根据不同模式解析条形码
//        String barcodeMode = textOptions.getBarcodeMode();
        PdfCodabarBarcode barcode;
        String value = null;
        if (field != null && !field.isEmpty()){
            if (utilData != null && utilData.getFields() != null){
                value = utilData.getFields().get(field);
            }
        }
        if (value == null){
            value = textOptions.getTitle();
        }
        // 设置字体
        PdfTrueTypeFont font = getFont(6, textOptions.getFontFamily(), textOptions.getFontWeight());

        barcode = new PdfCodabarBarcode(value);
//        barcode.setBarcodeToTextGapHeight(1f);
        barcode.setBarHeight((float) (position.getHeight()));
        barcode.setFont(font);
        barcode.setTextDisplayLocation(TextLocation.Bottom);
        barcode.setText(value);
        barcode.setEnableCheckDigit(true);
        barcode.setShowCheckDigit(true);
        barcode.setTextColor(new PdfRGBColor(hex2RGB(textOptions.getColor(), Color.BLACK)));
        // 打印位置
        barcode.draw(pageBase, position);
    }

    /**
     * 绘制文本
     * @param pageBase
     * @param textOptions
     * @param position
     */
    private void createString(PdfPageBase pageBase, TextOptions textOptions, Rectangle2D position) throws IllegalAccessException {
        String value = textOptions.getTitle();
        PdfTrueTypeFont font = getFont(textOptions.getFontSize(), textOptions.getFontFamily(), textOptions.getFontWeight());
        PdfSolidBrush brush = new PdfSolidBrush(new PdfRGBColor(hex2RGB(textOptions.getColor(), Color.BLACK)));
        pageBase.getCanvas().drawString(value, font, brush, position);
    }

    /**
     * 创建文本输入框
     * @param pageBase
     * @param textOptions
     * @param position
     * @return
     * @throws Exception
     */
    private void createTextBoxField(PdfPageBase pageBase, TextOptions textOptions, Rectangle2D position) throws Exception {
        String field = textOptions.getField();
        String title = textOptions.getTitle();
        // 创建textBox输入框
        PdfTextBoxField textBoxField = new PdfTextBoxField(pageBase, field);
        textBoxField.setMultiline(false);
        // 设置打印位置
        textBoxField.setBounds(position);
        // 设置背景颜色
        textBoxField.setBackColor(new PdfRGBColor(hex2RGB(textOptions.getBackgroundColor(), Color.WHITE)));
        // 边框颜色
        textBoxField.setBorderColor(new PdfRGBColor(hex2RGB(textOptions.getBorderColor(), Color.BLACK)));
        textBoxField.setBorderWidth(getBorderWidth(textOptions.getBorderWidth(), 0f));
        // todo 边框样式
//        textBoxField.setBorderStyle();
        // todo 内边距
//
        // 文本框字体样式
        textBoxField.setFont(getFont(textOptions.getFontSize(), textOptions.getFontFamily(), textOptions.getFontWeight()));

        // todo 字体颜色
//
        // 设置值
        String textValue = "";
        if (title != null && !title.isEmpty()){
            boolean hideTitle = textOptions.isHideTitle();
            String utilDataValue = null;
            // 获取字段中的值
            if (utilData != null && utilData.getFields() != null) {
                utilDataValue = utilData.getFields().get(textOptions.getField());
            }
            // 是否隐藏标题
            if (hideTitle){
                title = null;
            }
            // 若不隐藏标题，拼接title与utilDataValue
            if (title != null){
                StringBuilder stringBuilder = new StringBuilder(title);
                stringBuilder.append("：");
                if (utilDataValue != null){
                    stringBuilder.append(utilDataValue);
                }
                textValue = stringBuilder.toString();
            }else {
                // 标题为空，传入数据不为空，进行赋值
                if (utilDataValue != null){
                    textValue = utilDataValue;
                }
            }
        }
        textBoxField.setText(textValue);
        // 水平居中
        textBoxField.setTextAlignment(PdfTextAlignment.valueOf(StringUtils.capitalize(textOptions.getTextAlign().name().toLowerCase())));
        // todo 垂直居中
//
        pdfDocument.getForm().getFields().add(textBoxField);
        // todo addCache
    }

    /**
     * 获取字体
     * @param fontSize 字体大小
     * @param fontFamily 字体
     * @param width 字体粗细
     * @return
     * @throws IllegalAccessException
     */
    private PdfTrueTypeFont getFont(double fontSize, String fontFamily, String width) throws IllegalAccessException {
        if (width != null && !width.isEmpty()){
            // 正则匹配是否为数字，若为数字，设置字体大小
            Pattern pattern = Pattern.compile("[0-9]*");
            if (pattern.matcher(width).matches()) {
                // 转换为数字
                int intWidth = Integer.parseInt(width);
                return getFont(fontSize, fontFamily, intWidth);
            }
        }
        width = "plain";
        if (fontFamily == null || fontFamily.isEmpty()){
            fontFamily = "宋体";
        }
        Field[] declaredFields = Font.class.getDeclaredFields();
        int fontWidth = Font.PLAIN;
        for (Field declaredField : declaredFields) {
            if (declaredField.getName().equals(width.toUpperCase())) {
                fontWidth = (int) declaredField.get(null);
                break;
            }
        }
        if (fontSize <= 0){
            fontSize = 9;
        }
        return new PdfTrueTypeFont(new Font(fontFamily, fontWidth, (int) fontSize), true);
    }

    private PdfTrueTypeFont getFont() throws IllegalAccessException {
        return this.getFont(0, "", 0);
    }

    private PdfTrueTypeFont getFont(double fontSize, String fontFamily, int fontWidth) throws IllegalAccessException {
        if (fontFamily == null || fontFamily.isEmpty()){
            fontFamily = "宋体";
        }
        if (fontSize <= 0){
            fontSize = 9;
        }
        if (fontWidth <= 0){
            fontWidth = Font.PLAIN;
        }
        return new PdfTrueTypeFont(new Font(fontFamily, fontWidth, (int) fontSize), true);
    }

    /**
     * 获取边框大小
     * @param width
     * @param defaultValue
     * @return
     * @throws IllegalAccessException
     */
    private float getBorderWidth(String width, float defaultValue) throws IllegalAccessException {
        if (width != null && !width.isEmpty()){
            return Font.getFont(width).getSize2D();
        }
        return defaultValue;
    }

    /**
     * 十六进制颜色转换为RGB颜色
     * @param hexStr
     * @param defaultColor
     * @return
     */
    private Color hex2RGB(String hexStr, Color defaultColor){
        if(hexStr != null && !"".equals(hexStr) && hexStr.length() == 7){
            int R = Integer.valueOf(hexStr.substring( 1, 3 ), 16);
            int G = Integer.valueOf(hexStr.substring( 3, 5 ), 16);
            int B = Integer.valueOf(hexStr.substring( 5, 7 ), 16);
            return new Color(R, G, B);
        }
        return defaultColor;
    }


}
